Skip to content

fix: focus first unwatched episode in details view (#117) - #124

Merged
ProdigyV21 merged 1 commit into
mainfrom
fix/focus-first-unwatched-episode
Apr 5, 2026
Merged

fix: focus first unwatched episode in details view (#117)#124
ProdigyV21 merged 1 commit into
mainfrom
fix/focus-first-unwatched-episode

Conversation

@ProdigyV21

Copy link
Copy Markdown
Owner

Summary

Closes #117.

In the episode list on the details screen, the first unwatched episode is now focused by default instead of always focusing episode 1. Particularly valuable for long-running shows/anime where users had to scroll past everything they had already watched.

Root cause

DetailsViewModel.loadDetails() computes nextUnwatchedEpisode on line 496 and uses it for the play button label ("Continue S1E3"), but initialEpisodeIndex at line 493-495 always defaulted to 0 when the caller did not pass an explicit episode target (which is the normal case for navigation from the home grid, search, catalogs, etc. — only Continue Watching tiles pass a target episode).

Fix

Replaced the if/else 0 with a three-way when:

val initialEpisodeIndex = when {
    targetEpisodeForRow != null ->
        decoratedEpisodes.indexOfFirst { it.episodeNumber == targetEpisodeForRow }.coerceAtLeast(0)
    nextUnwatchedEpisode != null ->
        decoratedEpisodes.indexOf(nextUnwatchedEpisode).coerceAtLeast(0)
    else -> 0
}

The watched-status decoration already runs a few lines earlier (pulls from Trakt for linked users via traktRepository.getWatchedEpisodesForShow(mediaId), falls back to local season progress otherwise), so this reuses existing data with zero extra network calls or work.

Edge cases handled

  • Explicit target from Continue Watching: unchanged behavior — the user still lands on the exact episode they were watching.
  • Fully watched season: nextUnwatchedEpisode is null, falls back to index 0 (episode 1). User can use the season selector to jump forward.
  • Brand new show (nothing watched): nextUnwatchedEpisode is episode 1, indexOf(...) returns 0, same as the old default.
  • Switching seasons on an already-loaded show: the LaunchedEffect in DetailsScreen.kt:268 keys on (initialEpisodeIndex, episodes) — both change when a new season loads, so the new focus index is picked up correctly.
  • Index-0 re-sync guard: DetailsScreen.kt:269 only re-syncs when initialEpisodeIndex > 0. When my fix returns 0, the screen-level episodeIndex default is also 0, so no re-sync is needed. No behavior change for shows where episode 1 is unwatched.

Risk

Minimal. Single-file, 13-line change. Reuses existing watched-episode data. No new network calls, no new allocations on a hot path.

Previously `initialEpisodeIndex` defaulted to 0 when the caller did not pass
an explicit episode target (e.g., navigating to a show from the home grid
rather than from a Continue Watching tile). That always focused episode 1
of the current season, forcing users to scroll past every episode they had
already watched before reaching the next unwatched one — particularly
painful on long-running anime with hundreds of episodes.

`nextUnwatchedEpisode` was already computed on the line below and used to
build the "Continue SxEy" play button label, but was never fed back into
the initial focus index.

Now:
- If the caller passed an explicit episode target, focus it (unchanged).
- Otherwise focus the first unwatched episode in the loaded season.
- If every episode in the current season is already watched, fall back to
  episode 1 so the user can switch seasons from the normal starting point.

This reuses the watched-status decoration that already runs a few lines
earlier (from Trakt for Trakt-linked users, falling back to local season
progress), so there is no extra work or network call.

The `> 0` guard in DetailsScreen.LaunchedEffect still handles the index-0
case correctly because the screen-level `episodeIndex` default is also 0.

Closes #117
@ProdigyV21
ProdigyV21 merged commit a099ce6 into main Apr 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Episode view: focus first unwatched

1 participant